import tkinter as tk
from tkinter import ttk, messagebox, Canvas, PhotoImage
import cv2
import numpy as np
import pytesseract
from PIL import Image, ImageTk, ImageDraw
from datetime import datetime, date
import threading
import time
import win32gui
import win32ui
import win32con
import ctypes
import configparser
import json
import requests
import logging
import aiohttp
import asyncio
from screeninfo import get_monitors

CONFIG_FILE = 'config.ini'

# --- 全局变量 ---
window_title = ""
target1_region = None
target2_region = None
is_monitoring = False

# 配置日志
logging.basicConfig(
    level=logging.INFO,  # 设置日志级别
    format='%(asctime)s - %(levelname)s - %(message)s',  # 日志格式
    handlers=[
        logging.FileHandler('myapp.log', encoding='utf-8'),  # 写入文件
        logging.StreamHandler()  # 同时输出到控制台（可选）
    ]
)
logger = logging.getLogger(__name__)


# --- 核心功能函数 ---

def read_config():
    """读取配置文件"""
    config = configparser.ConfigParser()
    config.read(CONFIG_FILE, encoding='utf-8')
    return config


def update_config(section, key, value):
    """更新配置文件中指定的键值"""
    config = read_config()

    if section not in config:
        print(f"节 [{section}] 不存在，正在创建...")
        logger.info(f"节 [{section}] 不存在，正在创建...")
        config[section] = {}

    old_value = config.get(section, key, fallback=None)
    config[section][key] = str(value)

    # 写回文件
    with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
        config.write(f)

    print(f"配置更新成功: [{section}] {key} = '{value}' (原值: {old_value})")
    logger.info(f"配置更新成功: [{section}] {key} = '{value}' (原值: {old_value})")


def get_config(section, key, fallback=None):
    """获取配置项"""
    config = read_config()
    return config.get(section, key, fallback=fallback)


def find_window_fuzzy(partial_title):
    """模糊查找窗口（不区分大小写）"""

    def callback(hwnd, results):
        if win32gui.IsWindowVisible(hwnd):
            title = win32gui.GetWindowText(hwnd)
            if partial_title.lower() in title.lower():
                results.append(hwnd)
        return True

    results = []
    win32gui.EnumWindows(callback, results)
    return results[0] if results else None


def capture_window_advanced(hwnd):
    """使用 PrintWindow 截图（支持最小化）"""
    left, top, right, bottom = win32gui.GetWindowRect(hwnd)
    width = right - left
    height = bottom - top
    hwnd_dc = win32gui.GetWindowDC(hwnd)
    mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
    save_dc = mfc_dc.CreateCompatibleDC()
    save_bitmap = win32ui.CreateBitmap()
    save_bitmap.CreateCompatibleBitmap(mfc_dc, width, height)
    save_dc.SelectObject(save_bitmap)
    result = ctypes.windll.user32.PrintWindow(hwnd, save_dc.GetSafeHdc(), 0x00000002)
    if result == 0:
        save_dc.BitBlt((0, 0), (width, height), mfc_dc, (0, 0), win32con.SRCCOPY)
    signed_ints = save_bitmap.GetBitmapBits(True)
    img = np.frombuffer(signed_ints, dtype='uint8')
    img.shape = (height, width, 4)
    img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
    win32gui.DeleteObject(save_bitmap.GetHandle())
    save_dc.DeleteDC()
    mfc_dc.DeleteDC()
    win32gui.ReleaseDC(hwnd, hwnd_dc)
    return img, (left, top)


def ocr_at_rect(img, rect):
    """在指定矩形区域内进行OCR识别"""
    x, y, w, h = rect
    roi = img[y:y + h, x:x + w]
    gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
    scale = 2
    resized = cv2.resize(gray, None, fx=scale, fy=scale, interpolation=cv2.INTER_CUBIC)
    blurred = cv2.GaussianBlur(resized, (3, 3), 0)
    _, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    if np.mean(thresh) > 128:
        thresh = 255 - thresh
    config = '--psm 7 --oem 3 -c tessedit_char_whitelist=0123456789'
    text = pytesseract.image_to_string(thresh, config=config).strip()
    return text


def start_monitoring():
    """后台监控线程，每5分钟执行一次OCR"""
    global is_monitoring
    window_title = get_config('base', 'title')
    times = get_config('base', 'time')
    x1 = get_config('location', 'x1')
    y1 = get_config('location', 'y1')
    w1 = get_config('location', 'w1')
    h1 = get_config('location', 'h1')

    x2 = get_config('location', 'x2')
    y2 = get_config('location', 'y2')
    w2 = get_config('location', 'w2')
    h2 = get_config('location', 'h2')
    location1 = (x1, y1, w1, h1)
    location2 = (x2, y2, w2, h2)
    while is_monitoring:
        time.sleep(int(times))
        if not is_monitoring:
            break
        hwnd = find_window_fuzzy(window_title)
        if not hwnd:
            print(f"监控: 未找到窗口 '{window_title}'")
            logger.info(f"监控: 未找到窗口 '{window_title}'")
            continue
        img, _ = capture_window_advanced(hwnd)
        if img is None:
            print("监控: 截图失败")
            logger.info("监控: 截图失败")
            continue
        data = ocrImage(img, location1, location2)
        print(f"搜索结果:{data}")
        logger.info(f"搜索结果:{data}")
        sendData(data)


def find_numbers_in_region_v2(img, search_x, search_y, search_w, search_h, num1, num2):
    """
    使用 image_to_boxes 实现字符级定位，再组合成完整数字位置
    """
    roi = img[search_y:search_y + search_h, search_x:search_x + search_w]
    gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)

    scale = 2
    resized = cv2.resize(gray, None, fx=scale, fy=scale, interpolation=cv2.INTER_CUBIC)
    blurred = cv2.GaussianBlur(resized, (3, 3), 0)
    _, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    if np.mean(thresh) > 128:
        thresh = 255 - thresh

    preprocessed_roi = thresh
    config = '--psm 13 --oem 1 -c tessedit_char_whitelist=0123456789'

    try:
        boxes_data = pytesseract.image_to_boxes(preprocessed_roi, config=config, output_type=pytesseract.Output.DICT)
    except Exception as e:
        print(f"OCR 处理失败: {e}")
        logger.info(f"OCR 处理失败: {e}")
        return None, None

    if 'char' not in boxes_data:
        print("OCR 输出中缺少 'char' 键。boxes_data:", boxes_data)
        logger.info("OCR 输出中缺少 'char' 键。boxes_data:", boxes_data)
        return None, None

    n_boxes = len(boxes_data['char'])

    current_text = ""
    current_start = None
    current_end = None
    rect1 = rect2 = None

    for i in range(n_boxes):
        char = boxes_data['char'][i]
        x, y, w, h = boxes_data['left'][i], boxes_data['top'][i], boxes_data['right'][i], boxes_data['bottom'][i]

        if char.isdigit():
            if not current_text:
                current_text = char
                current_start = (x, y)
                current_end = (w, h)
            else:
                current_text += char
                current_end = (w, h)
        else:
            if current_text:
                if num1 == current_text and rect1 is None:
                    x1, y1 = current_start
                    x2, y2 = current_end
                    abs_x = search_x + x1
                    abs_y = search_y + (roi.shape[0] - y2)
                    width = (x2 - x1)
                    height = (y2 - y1)
                    rect1 = (abs_x, abs_y, width, height)
                if num2 == current_text and rect2 is None:
                    x1, y1 = current_start
                    x2, y2 = current_end
                    abs_x = search_x + x1
                    abs_y = search_y + (roi.shape[0] - y2)
                    width = (x2 - x1)
                    height = (y2 - y1)
                    rect2 = (abs_x, abs_y, width, height)
                current_text = ""

    if current_text:
        if num1 == current_text and rect1 is None:
            x1, y1 = current_start
            x2, y2 = current_end
            abs_x = search_x + x1
            abs_y = search_y + (roi.shape[0] - y2)
            width = (x2 - x1)
            height = (y2 - y1)
            rect1 = (abs_x, abs_y, width, height)
        if num2 == current_text and rect2 is None:
            x1, y1 = current_start
            x2, y2 = current_end
            abs_x = search_x + x1
            abs_y = search_y + (roi.shape[0] - y2)
            width = (x2 - x1)
            height = (y2 - y1)
            rect2 = (abs_x, abs_y, width, height)

    return rect1, rect2


# --- GUI 应用 ---
class OCRMonitorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("数字定位监控器 - 带区域预览")

        monitors = get_monitors()
        primary_monitor = monitors[0]

        self.root.geometry(f"1000x{primary_monitor.height}")
        self.root.resizable(False, False)

        self.create_widgets()

    def create_widgets(self):
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # === 输入区域 ===
        input_frame = ttk.LabelFrame(main_frame, text="参数设置", padding="10")
        input_frame.grid(row=0, column=0, columnspan=2, sticky=tk.W, pady=5)

        window_title = get_config('base', 'title')
        url = get_config('base', 'url')
        times = get_config('base', 'time')
        x1 = get_config('location', 'x1')
        y1 = get_config('location', 'y1')
        w1 = get_config('location', 'w1')
        h1 = get_config('location', 'h1')

        x2 = get_config('location', 'x2')
        y2 = get_config('location', 'y2')
        w2 = get_config('location', 'w2')
        h2 = get_config('location', 'h2')

        row = 0
        # 窗口标题
        ttk.Label(input_frame, text="窗口标题:").grid(row=row, column=0, sticky=tk.W, pady=3)
        self.entry_title = ttk.Entry(input_frame, width=100)
        self.entry_title.grid(row=row, column=1, pady=3)
        self.entry_title.insert(0, window_title)

        row += 1
        ttk.Label(input_frame, text="远程保存地址:").grid(row=row, column=0, sticky=tk.W, pady=3)
        self.entry_url = ttk.Entry(input_frame, width=100)
        self.entry_url.grid(row=row, column=1, pady=3)
        self.entry_url.insert(0, url)

        row += 1
        ttk.Label(input_frame, text="调用间隔(秒):").grid(row=row, column=0, sticky=tk.W, pady=3)
        self.entry_time = ttk.Entry(input_frame, width=100)
        self.entry_time.grid(row=row, column=1, pady=3)
        self.entry_time.insert(0, times)

        row += 1
        ttk.Separator(input_frame, orient='horizontal').grid(row=row, column=0, columnspan=2, sticky='ew', pady=5)
        row += 1
        # 数字1
        ttk.Label(input_frame, text="数字目标 1:").grid(row=row, column=0, sticky=tk.W, pady=3)
        # self.entry_num1 = ttk.Entry(input_frame, width=40)
        # self.entry_num1.grid(row=row, column=1, pady=3)
        # self.entry_num1.insert(0, "4677")

        # 数字目标 1 的搜索区域
        # row += 1
        ttk.Label(input_frame, text="目标1 搜索区域 X:").grid(row=row, column=0, sticky=tk.W, pady=3)
        self.entry_num1_x = ttk.Entry(input_frame, width=10)
        self.entry_num1_x.grid(row=row, column=1, sticky=tk.W, padx=(0, 5))
        self.entry_num1_x.insert(0, x1)
        ttk.Label(input_frame, text="Y:").grid(row=row, column=1, sticky=tk.W, padx=(80, 0))
        self.entry_num1_y = ttk.Entry(input_frame, width=10)
        self.entry_num1_y.grid(row=row, column=1, sticky=tk.W, padx=(100, 0))
        self.entry_num1_y.insert(0, y1)

        row += 1
        ttk.Label(input_frame, text="Width:").grid(row=row, column=0, sticky=tk.W, pady=3)
        self.entry_num1_w = ttk.Entry(input_frame, width=10)
        self.entry_num1_w.grid(row=row, column=1, sticky=tk.W, padx=(0, 5))
        self.entry_num1_w.insert(0, w1)
        ttk.Label(input_frame, text="Height:").grid(row=row, column=1, sticky=tk.W, padx=(80, 0))
        self.entry_num1_h = ttk.Entry(input_frame, width=10)
        self.entry_num1_h.grid(row=row, column=1, sticky=tk.W, padx=(120, 0))
        self.entry_num1_h.insert(0, h1)

        row += 1
        # 分隔线
        ttk.Separator(input_frame, orient='horizontal').grid(row=row, column=0, columnspan=2, sticky='ew', pady=5)
        row += 1

        # 数字2
        ttk.Label(input_frame, text="数字目标 2:").grid(row=row, column=0, sticky=tk.W, pady=3)
        # self.entry_num2 = ttk.Entry(input_frame, width=40)
        # self.entry_num2.grid(row=row, column=1, pady=3)
        # self.entry_num2.insert(0, x2)

        # 数字目标 2 的搜索区域
        # row += 1
        ttk.Label(input_frame, text="目标2 搜索区域 X:").grid(row=row, column=0, sticky=tk.W, pady=3)
        self.entry_num2_x = ttk.Entry(input_frame, width=10)
        self.entry_num2_x.grid(row=row, column=1, sticky=tk.W, padx=(0, 5))
        self.entry_num2_x.insert(0, x2)
        ttk.Label(input_frame, text="Y:").grid(row=row, column=1, sticky=tk.W, padx=(80, 0))
        self.entry_num2_y = ttk.Entry(input_frame, width=10)
        self.entry_num2_y.grid(row=row, column=1, sticky=tk.W, padx=(100, 0))
        self.entry_num2_y.insert(0, y2)

        row += 1
        ttk.Label(input_frame, text="Width:").grid(row=row, column=0, sticky=tk.W, pady=3)
        self.entry_num2_w = ttk.Entry(input_frame, width=10)
        self.entry_num2_w.grid(row=row, column=1, sticky=tk.W, padx=(0, 5))
        self.entry_num2_w.insert(0, w2)
        ttk.Label(input_frame, text="Height:").grid(row=row, column=1, sticky=tk.W, padx=(80, 0))
        self.entry_num2_h = ttk.Entry(input_frame, width=10)
        self.entry_num2_h.grid(row=row, column=1, sticky=tk.W, padx=(120, 0))
        self.entry_num2_h.insert(0, h2)

        # === 按钮区域 ===
        row += 1
        btn_frame = ttk.Frame(input_frame)
        btn_frame.grid(row=row, column=0, columnspan=2, pady=10)
        ttk.Button(btn_frame, text="预览区域", command=self.preview_region).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="开始定位并监控", command=self.start).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="停止监控", command=self.stop).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="立即识别一次", command=self.quick_ocr).pack(side=tk.LEFT, padx=5)

        # === 日志区域 ===
        log_frame = ttk.LabelFrame(main_frame, text="状态日志", padding="10")
        log_frame.grid(row=1, column=0, columnspan=2, pady=10, sticky=tk.W + tk.E)

        self.log_text = tk.Text(log_frame, height=16, width=80)
        self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.log_text.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.log_text['yscrollcommand'] = scrollbar.set

        # === 图像预览区域 ===
        preview_frame = ttk.LabelFrame(main_frame, text="区域预览", padding="10")
        preview_frame.grid(row=2, column=0, columnspan=2, pady=5, sticky=tk.W + tk.E)

        self.canvas = Canvas(preview_frame, width=760, height=400, bg="lightgray", relief="sunken")
        self.canvas.pack(fill=tk.BOTH, expand=True)

    def log(self, msg):
        self.log_text.insert(tk.END, msg + "\n")
        self.log_text.see(tk.END)

    def show_enlarged_image(self, pil_img):
        """在一个新的窗口中显示放大的图片"""
        new_window = tk.Toplevel(self.root)
        new_window.title("放大后的图片")

        # 假设你想将图片放大两倍
        enlarged_img = pil_img.resize((pil_img.width, pil_img.height), Image.Resampling.LANCZOS)
        # enlarged_img = pil_img.resize((pil_img.width * 2, pil_img.height * 2), Image.Resampling.LANCZOS)
        tk_enlarged_img = ImageTk.PhotoImage(enlarged_img)

        label = tk.Label(new_window, image=tk_enlarged_img)
        label.image = tk_enlarged_img  # 防止垃圾回收导致图片不显示
        label.pack()

        # 如果需要，可以在这里设置新窗口的大小
        new_window.geometry(f"{enlarged_img.width}x{enlarged_img.height}")

    def preview_region(self):
        """预览指定区域截图"""
        global target1_region, target2_region
        try:
            x1 = int(self.entry_num1_x.get())
            y1 = int(self.entry_num1_y.get())
            w1 = int(self.entry_num1_w.get())
            h1 = int(self.entry_num1_h.get())
            x2 = int(self.entry_num2_x.get())
            y2 = int(self.entry_num2_y.get())
            w2 = int(self.entry_num2_w.get())
            h2 = int(self.entry_num2_h.get())
            target1_region = (x1, y1, w1, h1)
            target2_region = (x2, y2, w2, h2)

        except ValueError:
            messagebox.showerror("错误", "X, Y, Width, Height 必须是整数！")
            return

        window_title_input = self.entry_title.get().strip()
        if not window_title_input:
            messagebox.showwarning("警告", "请输入窗口标题！")
            return

        hwnd = find_window_fuzzy(window_title_input)
        if not hwnd:
            messagebox.showerror("错误", f"未找到包含 '{window_title_input}' 的窗口！")
            return
        img, (win_x, win_y) = capture_window_advanced(hwnd)

        if img is None or img.size == 0:
            messagebox.showerror("错误", "截图为空或失败！")
            return

        times = self.entry_time.get()
        url = self.entry_url.get()
        update_config('base', 'title', window_title_input)
        update_config('base', 'time', times)
        update_config('base', 'url', url)
        update_config('location', 'x1', x1)
        update_config('location', 'y1', y1)
        update_config('location', 'w1', w1)
        update_config('location', 'h1', h1)

        update_config('location', 'x2', x2)
        update_config('location', 'y2', y2)
        update_config('location', 'w2', w2)
        update_config('location', 'h2', h2)

        # 创建 PIL 图像
        rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        pil_img = Image.fromarray(rgb_img)

        # 在图像上画出搜索区域
        draw = ImageDraw.Draw(pil_img)

        # 绘制目标1区域
        # 现在 x1, y1 是相对于屏幕的，我们需要转换为相对于客户区左上角的坐标
        # draw_x1 = x1 - win_x
        # draw_y1 = y1 - win_y
        draw_x1 = x1
        draw_y1 = y1
        if 0 <= draw_x1 < pil_img.width and 0 <= draw_y1 < pil_img.height:

            draw.rectangle(
                [draw_x1, draw_y1, draw_x1 + w1, draw_y1 + h1],
                outline="red", width=3
            )
            self.log(f"✅ 已标出目标1区域 ({x1}, {y1}, {w1}, {h1})")
        else:
            self.log("⚠️ 目标1区域超出窗口范围，无法绘制边框")

        # 绘制目标2区域
        # draw_x2 = x2 - win_x
        # draw_y2 = y2 - win_y
        draw_x2 = x2
        draw_y2 = y2
        if 0 <= draw_x2 < pil_img.width and 0 <= draw_y2 < pil_img.height:

            draw.rectangle(
                [draw_x2, draw_y2, draw_x2 + w2, draw_y2 + h2],
                outline="yellow", width=3
            )
            self.log(f"✅ 已标出目标2区域 ({x2}, {y2}, {w2}, {h2})")
        else:
            self.log("⚠️ 目标2区域超出窗口范围，无法绘制边框")

        # 缩放以适应 Canvas
        canvas_width = self.canvas.winfo_width()
        canvas_height = self.canvas.winfo_height()
        scale = min(canvas_width / pil_img.width, canvas_height / pil_img.height, 1.0)
        new_size = (int(pil_img.width * scale), int(pil_img.height * scale))
        resized_img = pil_img.resize(new_size, Image.Resampling.LANCZOS)

        # 转为 Tkinter 可用
        self.tk_img = ImageTk.PhotoImage(resized_img)

        # 清空画布并显示
        self.canvas.delete("all")
        self.canvas.create_image(0, 0, anchor=tk.NW, image=self.tk_img)
        self.canvas.config(scrollregion=self.canvas.bbox(tk.ALL))

        self.canvas.bind("<Double-Button-1>", lambda event: self.show_enlarged_image(pil_img))

    def start(self):
        self.log("开始执行----开始定位并监控中------")
        global window_title, target1_region, target2_region, is_monitoring

        window_title = self.entry_title.get().strip()

        try:
            x1 = int(self.entry_num1_x.get())
            y1 = int(self.entry_num1_y.get())
            w1 = int(self.entry_num1_w.get())
            h1 = int(self.entry_num1_h.get())
            x2 = int(self.entry_num2_x.get())
            y2 = int(self.entry_num2_y.get())
            w2 = int(self.entry_num2_w.get())
            h2 = int(self.entry_num2_h.get())
            target1_region = (x1, y1, w1, h1)
            target2_region = (x2, y2, w2, h2)
            location1 = target1_region
            location2 = target2_region

        except ValueError:
            messagebox.showerror("错误", "X, Y, Width, Height 必须是整数！")
            return

        if not window_title:
            messagebox.showwarning("警告", "请输入窗口标题！")
            return

        # self.log(f"🔍 查找窗口: '{window_title}'")

        hwnd = find_window_fuzzy(window_title)
        if not hwnd:
            messagebox.showerror("错误", "未找到匹配的窗口！")
            return

        img, _ = capture_window_advanced(hwnd)
        if img is None:
            self.log("监控: 截图失败")
        # self.log(f"监控: {text1} | {text2}")
        data = ocrImage(img, location1, location2)
        self.log(f"搜索结果:{data}")
        sendData(data)

        is_monitoring = True
        thread = threading.Thread(target=start_monitoring, daemon=True)
        thread.start()
        times = self.entry_time.get().strip()
        self.log(f"🟢 监控已启动，每{times}秒识别一次...")

    def stop(self):
        global is_monitoring
        is_monitoring = False
        self.log("🔴 监控已停止")

    def quick_ocr(self):
        self.log("开始执行----快速定位执行一次------")
        global window_title
        window_title = get_config('base', 'title')
        if not window_title:
            messagebox.showwarning("警告", "请先启动监控！")
            return

        hwnd = find_window_fuzzy(window_title)
        if not hwnd:
            self.log("❌ 窗口未找到")
            return

        img, _ = capture_window_advanced(hwnd)
        if img is None:
            self.log("监控: 截图失败")
        x1 = get_config('location', 'x1')
        y1 = get_config('location', 'y1')
        w1 = get_config('location', 'w1')
        h1 = get_config('location', 'h1')

        x2 = get_config('location', 'x2')
        y2 = get_config('location', 'y2')
        w2 = get_config('location', 'w2')
        h2 = get_config('location', 'h2')
        location1 = (x1, y1, w1, h1)
        location2 = (x2, y2, w2, h2)
        data = ocrImage(img, location1, location2)
        self.log(f"搜索结果:{data}")
        sendData(data)


def ocrImage(image, location1, location2) -> dict:
    # 指定要识别的区域坐标 (x, y, width, height)
    # x, y 是左上角坐标
    # width, height 是区域的宽和高
    # roi_x, roi_y, roi_width, roi_height = 1680, 335, 50, 23  # 示例坐标
    # roi_x1, roi_y1, roi_width1, roi_height1 = 1810, 438, 50, 23  # 示例坐标
    print(f"位置1:{location1}")
    print(f"位置2:{location2}")
    logger.info(f"位置1:{location1}")
    logger.info(f"位置2:{location2}")
    roi_x, roi_y, roi_width, roi_height = map(int, location1)
    roi_x1, roi_y1, roi_width1, roi_height1 = map(int, location2)

    # --- 步骤 1: 加载图像 ---
    # image = cv2.imread(image_path)
    # if image is None:
    #     raise FileNotFoundError(f"无法加载图像: {image_path}")

    # --- 步骤 2: 提取指定区域 (ROI) ---
    roi = image[roi_y:roi_y + roi_height, roi_x:roi_x + roi_width]
    roi1 = image[roi_y1:(roi_y1 + roi_height1), roi_x1:(roi_x1 + roi_width1)]

    # --- 步骤 3: (可选) 对ROI进行预处理以提高OCR准确性 ---
    # 转换为灰度图
    try:
        gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
        gray_roi1 = cv2.cvtColor(roi1, cv2.COLOR_BGR2GRAY)
    except Exception:
        messagebox.showwarning("警告", "请不要将识别窗口关闭或最小化！\n 调整后重新启动程序!")
        logger.info("警告", "请不要将识别窗口关闭或最小化！\n 调整后重新启动程序!")
        global is_monitoring
        is_monitoring = False

    # 二值化 (可选，根据图像质量调整)
    # _, binary_roi = cv2.threshold(gray_roi, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    # 或者使用自适应阈值
    # binary_roi = cv2.adaptiveThreshold(gray_roi, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)

    # 去噪 (可选)
    # denoised_roi = cv2.medianBlur(gray_roi, 3)

    # 放大图像 (可选，有时对小字体有帮助)
    # scale_factor = 2
    # enlarged_roi = cv2.resize(denoised_roi, None, fx=scale_factor, fy=scale_factor, interpolation=cv2.INTER_CUBIC)

    # 在这个例子中，我们使用灰度图
    preprocessed_roi = gray_roi
    preprocessed_roi1 = gray_roi1

    # --- 步骤 4: 使用Tesseract进行OCR识别 ---
    # 可以设置OCR配置参数
    # 例如: '--psm 6' (假设为单个均匀文本块), '--oem 3' (使用LSTM OCR引擎)
    # 'lang' 参数指定语言，例如 'chi_sim' (简体中文), 'eng' (英文), 'chi_sim+eng' (中英文)
    config = '--psm 6 --oem 3 -l eng'  # 根据需求调整
    # config = '--psm 6 --oem 3 -l chi_sim+eng'  # 识别中英文

    text = pytesseract.image_to_string(preprocessed_roi, config=config)
    text1 = pytesseract.image_to_string(preprocessed_roi1, config=config)

    # 清理结果 (去除换行符、多余空格等)
    recognized_text = text.strip()
    recognized_text1 = text1.strip()

    # --- 步骤 5: 输出结果 ---
    print(f"在区域 ({roi_x}, {roi_y}, {roi_width}, {roi_height}) 内识别到的文本:")
    print(recognized_text)

    print(f"在区域 ({roi_x1}, {roi_y1}, {roi_width1}, {roi_height1}) 内识别到的文本:")
    print(recognized_text1)
    logger.info(f"在区域 ({roi_x}, {roi_y}, {roi_width}, {roi_height}) 内识别到的文本:")
    logger.info(recognized_text)

    logger.info(f"在区域 ({roi_x1}, {roi_y1}, {roi_width1}, {roi_height1}) 内识别到的文本:")
    logger.info(recognized_text1)

    # --- (可选) 可视化 ---
    # 在原图上绘制ROI区域
    # cv2.rectangle(image, (roi_x, roi_y), (roi_x + roi_width, roi_y + roi_height), (0, 255, 0), 2)
    # cv2.putText(image, "ROI", (roi_x, roi_y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

    # 在原图上绘制ROI区域
    # cv2.rectangle(image, (roi_x1, roi_y1), (roi_x1 + roi_width1, roi_y1 + roi_height1), (0, 255, 0), 2)
    # cv2.putText(image, "ROI", (roi_x1, roi_y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

    # 显示原图和ROI
    # cv2.imshow('Original Image with ROI', image)
    # cv2.imshow('Extracted ROI', preprocessed_roi)
    # cv2.imshow('Extracted ROI1', preprocessed_roi1)

    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    # save_dir = r'H:\py\image'
    # if not os.path.exists(save_dir):
    #     os.makedirs(save_dir)
    # --- (可选) 保存处理后的图像 ---
    # cv2.imwrite('H:\\py\\image\\output_with_roi.jpg', image)
    # cv2.imwrite('H:\\py\\image\\extracted_roi.jpg', preprocessed_roi)
    # cv2.imwrite('H:\\py\\image\\extracted_roi1.jpg', preprocessed_roi1)
    # incount=100&pickingcount=200
    return {
        "incount": recognized_text,
        "pickingcount": recognized_text1
    }


# 替换原有的 sendData 函数
async def async_send_data(info: dict):
    """异步发送数据到服务器"""
    url = get_config('base', 'url')
    append_dict_to_txt(info)
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    logger.info(f"data:{current_time};url:{url};params:{info}")

    try:
        async with aiohttp.ClientSession() as session:
            async with session.get(url, params=info) as response:
                logger.info(f"Response status: {response.status}")
                # 如果需要处理响应内容，可以在这里添加
                # response_text = await response.text()
    except Exception as e:
        print(f"发生了错误: {e}")
        logger.info(f"发生了错误: {e}")
    else:
        print("操作无误,已经将数据发往服务端")
        logger.info("操作无误,已经将数据发往服务端")


def sendData(info: dict):
    """
    异步执行数据发送任务
    使用线程运行异步函数，避免阻塞主线程
    """

    def run_async_task():
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            loop.run_until_complete(async_send_data(info))
        finally:
            loop.close()

    # 在单独的线程中运行异步任务
    thread = threading.Thread(target=run_async_task, daemon=True)
    thread.start()


def append_dict_to_txt(data_dict, filename='data.txt'):
    """
    将字典数据以指定格式追加写入到本地txt文件中。

    参数:
    data_dict (dict): 要写入的字典数据。
    filename (str): 目标txt文件的路径和名称。
    """
    # 获取当前时间，格式化为 'YYYY-MM-DD HH:MM:SS'
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

    # 将字典转换为JSON字符串
    # ensure_ascii=False 保证中文等非ASCII字符能正常显示
    # separators=(',', ':') 去掉默认的空格，使输出更紧凑（可选）
    json_str = json.dumps(data_dict, ensure_ascii=False, separators=(',', ':'))

    # 构建要写入的完整行
    line = f"{current_time} 抓取数据内容为 : {json_str}\n"

    # 以追加模式 ('a') 打开文件，并写入内容
    # encoding='utf-8' 确保能正确处理中文
    with open(filename, 'a', encoding='utf-8') as file:
        file.write(line)


# --- 主程序入口 ---
if __name__ == "__main__":
    root = tk.Tk()
    app = OCRMonitorApp(root)
    root.mainloop()
